<?php

namespace app\api\model\v1;

use app\api\model\dealer\Order as DealerOrderModel;
use app\api\model\User;
use app\api\model\User as UserModel;
use app\api\model\Goods as GoodsModel;
use app\api\model\Setting as SettingModel;
use app\api\model\UserCoupon as UserCouponModel;
use app\api\service\v1\order\PaySuccess;
use app\api\service\v1\Payment as PaymentService;
use app\api\service\order\source\Factory as OrderSourceFactory;
use app\common\library\MysicLog;
use app\common\library\wechat\Qrcode;
use app\common\library\wechat\WxPay;
use app\common\model\Order as OrderModel;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\enum\order\Status as OrderStatusEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\model\Wxapp as WxappModel;
use app\common\service\goods\source\Factory as FactoryStock;
use app\common\service\order\Complete as OrderCompleteService;
use app\common\exception\BaseException;
use app\common\library\helper;
use app\common\library\wechat\Abonus;
use think\Db;


/**
 * 订单模型
 * Class Order
 * @package app\api\model
 */
class Order extends OrderModel
{
    /**
     * 隐藏字段
     * @var array
     */
    protected $hidden = [
        'wxapp_id',
        'update_time'
    ];

    protected $log;
    public function __construct($data = [])
    {
        parent::__construct($data);
        $this->log = MysicLog::instance();
    }

    /**
     * 待支付订单详情
     * @param $orderNo
     * @return null|static
     */
    public static function getPayDetail($orderNo)
    {
        //if((self::where('order_id',$orderNo)->value('order_source'))==50){// 原修改记录: 2020/10/17 unknown
        if((self::where('order_no',$orderNo)->value('order_source'))==50){
            return self::get(['order_no' => $orderNo, 'pay_status' => 10, 'is_delete' => 0], ['user']);
        }else{
            return self::get(['order_no' => $orderNo, 'pay_status' => 10, 'is_delete' => 0], ['goods', 'user']);
        }

    }

    /**
     * 订单支付事件
     * @param int $payType
     * @return bool
     * @throws \think\exception\DbException
     */
    public function onPay($payType = PayTypeEnum::WECHAT)
    {

        // 判断订单状态
        $orderSource = OrderSourceFactory::getFactory($this['order_source']);
        if (!$orderSource->checkOrderStatusOnPay($this)) {
            $this->error = $orderSource->getError();
            return false;
        }
        // 余额支付
        if ($payType == PayTypeEnum::BALANCE) {

            if($this['balance_money']>0){
                $this->error = '该订单使用了零钱折扣不支持余额支付';
                return false;
            }

            if($this['coupon_id']!=0){
                $this->error = '该订单使用了优惠券折扣不支持余额支付';
                return false;
            }
            return $this->onPaymentByBalance($this['order_no']);
        }
        return true;
    }

    /**
     * 构建支付请求的参数
     * @param $user
     * @param $order
     * @param $payType
     * @param $payWay
     * @return array
     * @throws BaseException
     * @throws \think\exception\DbException
     */
    public function onOrderPayment($user, $order, $payType)
    {
        if ($payType == PayTypeEnum::WECHAT) {
            return $this->onPaymentByWechat($user, $order);
        }

        return [];
    }

    /**
     * 构建微信支付请求
     * @param $user
     * @param $order
     * @return array
     * @throws BaseException
     * @throws \think\exception\DbException
     */
    protected function onPaymentByWechat($user, $order)
    {
        return PaymentService::wechat(
            $user,
            $order['order_id'],
            $order['order_no'],
            $order['pay_price'],
            OrderTypeEnum::MASTER
        );
    }

    /**
     * 立即购买：获取订单商品列表
     * @param $goodsId
     * @param $goodsSkuId
     * @param $goodsNum
     * @return array
     */
    public function getOrderGoodsListByNow($goodsId, $goodsSkuId, $goodsNum)
    {
        // 商品详情
        /* @var GoodsModel $goods */
        $goods = GoodsModel::detail($goodsId);
        // 商品sku信息
        $goods['goods_sku'] = GoodsModel::getGoodsSku($goods, $goodsSkuId);
        // 商品列表
        $goodsList = [$goods->hidden(['category', 'content', 'image', 'sku'])];
        foreach ($goodsList as &$item) {
            // 商品单价
            $item['goods_price'] = $item['goods_sku']['goods_price'];
            // 商品购买数量
            $item['total_num'] = $goodsNum;
            $item['spec_sku_id'] = $item['goods_sku']['spec_sku_id'];
            // 商品购买总金额
            $item['total_price'] = helper::bcmul($item['goods_price'], $goodsNum);
        }
        return $goodsList;
    }

    /**
     * 余额支付标记订单已支付
     * @param $user
     * @param $order
     * @param $payWay
     * @return bool
     * @throws \think\exception\DbException
     */
    public function onPaymentByBalance($order,$payWay)
    {

        // 获取订单详情
        $PaySuccess = new PaySuccess($order['order_no']);

        // 发起余额支付
        $status = $PaySuccess->onPaySuccess(PayTypeEnum::BALANCE,$payWay);
        if (!$status) {
            $this->error = $PaySuccess->getError();
        }
        return $status;
    }




    /**
     * 用户中心订单列表
     * @param $user_id
     * @param string $type
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function getList($user_id, $type = 'all')
    {
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = PayStatusEnum::PENDING;
                $filter['order_status'] = 10;
                break;
            case 'delivery';
                $filter['pay_status'] = PayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'received';
                $filter['pay_status'] = PayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'comment';
                $filter['is_comment'] = 0;
                $filter['order_status'] = 30;
                break;
        }
        return $this->with(['goods.image'])
            ->where('user_id', '=', $user_id)
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->where(['order_source'=>['IN',[10,20,30]]])
            ->order(['create_time' => 'desc'])
            ->paginate(15, false, [
                'query' => \request()->request()
            ]);
    }

    /**
     * 取消订单
     * @param UserModel $user
     * @return bool|mixed
     */
    public function cancel($user)
    {
        if ($this['delivery_status']['value'] == 20) {
            $this->error = '已发货订单不可取消';
            return false;
        }
        // 订单取消事件
        return $this->transaction(function () use ($user) {
            // 订单是否已支付
            $isPay = $this['pay_status']['value'] == PayStatusEnum::SUCCESS;
            // 未付款的订单
            if ($isPay == false) {
                // 回退商品库存
                FactoryStock::getFactory($this['order_source'])->backGoodsStock($this['goods'], $isPay);
                // 回退用户优惠券
                $this['coupon_id'] > 0 && UserCouponModel::setIsUse($this['coupon_id'], false);
                // 回退用户积分
                $describe = "订单取消：{$this['order_no']}";
                $this['points_num'] > 0 && $user->setIncPoints($this['points_num'], $describe);
                // 回退用户零钱
                $this['balance_num'] > 0 && $user->setIncBalance($this['balance_num'], $describe,40);
            }
            //取消订单，改变分账状态
              
            // 更新订单状态
            return $this->save(['order_status' => $isPay ? OrderStatusEnum::APPLY_CANCEL : OrderStatusEnum::CANCELLED]);

        });
    }



    /**
     * 确认收货
     * @return bool|mixed
     */
    public function receipt()
    {
        // 验证订单是否合法
        // 条件1: 订单必须已发货
        // 条件2: 订单必须未收货
        if ($this['delivery_status']['value'] != 20 || $this['receipt_status']['value'] != 10) {
            $this->error = '该订单不合法';
            return false;
        }
        return $this->transaction(function () {
            // 更新订单状态
            $status = $this->save([
                'receipt_status' => 20,
                'receipt_time' => time(),
                'order_status' => 30
            ]);
//            // 获取已完成的订单
//            $completed = self::detail($this['order_id'], [
//                'user', 'address', 'goods', 'express',    // 用于好物圈
//            ]);
            // 执行订单完成后的操作
            $OrderCompleteService = new OrderCompleteService(OrderTypeEnum::MASTER);
            $OrderCompleteService->complete([$this], static::$wxapp_id);

//            //查询订单以及分账的用户
//            $Dividends = new Abonus($this['wxapp_id']);
//            $Dividends->getDivideList($this);
//            //分账完结
//            $res=$Dividends->finish($this);
//            if($res['return_code']=='SUCCESS' and $res['result_code']=='SUCCESS'){
//                //退款
//                $wxConfig = WxappModel::getWxappRedis($this['wxapp_id']);
//                $WxPay = new WxPay($wxConfig);
//                $WxPay->refund($this['transaction_id'],$this['pay_price'],0.09); //用户分红回退
//            }
            return $status;
        });
    }





    /**
     * 获取订单总数
     * @param $user
     * @param string $type
     * @return int|string
     * @throws \think\Exception
     */
    public function getCount($user, $type = 'all')
    {

        if ($user === false) {
            return false;
        }
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = PayStatusEnum::PENDING;
                break;
            case 'received';
                $filter['pay_status'] = PayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                break;
            case 'comment';
                $filter['order_status'] = 30;
                $filter['is_comment'] = 0;
                break;
        }
        return $this->where('user_id', '=', $user['user_id'])
            ->where('order_status', '<>', 20)
            ->where(['order_source'=>['NOT IN',[40,50]]])
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->count();
    }

    /**
     * 订单详情
     * @param $order_id
     * @param null $user_id
     * @return null|static
     * @throws BaseException
     * @throws \think\exception\DbException
     */
    public static function getUserOrderDetail($order_id, $user_id)
    {
        if (!$order = self::get([
            'order_id' => $order_id,
            'user_id' => $user_id,
        ], [
            'goods' => ['image', 'goods', 'refund'],
            'address', 'express', 'extract_shop'
        ])
        ) {
            throw new BaseException(['msg' => '订单不存在']);
        }
        return $order;
    }

    /**
     * 判断当前订单是否允许核销
     * @param static $order
     * @return bool
     */
    public function checkExtractOrder(&$order)
    {
        if (
            $order['pay_status']['value'] == PayStatusEnum::SUCCESS
            && $order['delivery_type']['value'] == DeliveryTypeEnum::EXTRACT
            && $order['delivery_status']['value'] == 10
        ) {
            return true;
        }
        $this->setError('该订单不能被核销');
        return false;
    }

    /**
     * 当前订单是否允许申请售后
     * @return bool
     */
    public function isAllowRefund()
    {
        // 必须是已发货的订单
        if ($this['delivery_status']['value'] != 20) {
            return false;
        }
        // 允许申请售后期限(天)
        $refundDays = SettingModel::getItem('trade')['order']['refund_days'];
        // 不允许售后
        if ($refundDays == 0) {
            return false;
        }
        // 当前时间超出允许申请售后期限
        if (
            $this['receipt_status'] == 20
            && time() > ($this['receipt_time'] + ((int)$refundDays * 86400))
        ) {
            return false;
        }
        return true;
    }

    /**
     * 设置错误信息
     * @param $error
     */
    protected function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    /**
     * 是否存在错误
     * @return bool
     */
    public function hasError()
    {
        return !empty($this->error);
    }

    /**
     *  *  余额支付
     * @param $user array
     * @param $order  array
     * @return array|bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function  onPaymentByBalances($user,$order)
    {
        //1.金额，2.支付方式

        $userDeal=db('dealer_user')->where(['user_id'=>$user['user_id'],'wxapp_id'=>$user['wxapp_id']])->find();
        //选择支付方式 10：储值余额，20.收益余额
        if($user['default_pay']==10 && $user['money']>=$order['pay_price']){
            return  array('pay_name'=>'储值余额','pay_type'=>10,'pay_price'=>$order['pay_price']);
        }elseif($user['default_pay']==10 && $user['money']<$order['pay_price']){
            if($userDeal['money']>=$order['pay_price']){
                return  array('pay_name'=>'收益余额','pay_type'=>20,'pay_price'=>$order['pay_price']);
            }else{
                $this->setError('余额不足，请选择微信支付');
                return false;
            }
        }elseif ($user['default_pay']==20 && $userDeal['money']>=$order['pay_price']){
            return array('pay_name'=>'收益余额','pay_type'=>20,'pay_price'=>$order['pay_price']);
        }elseif ($user['default_pay']==20 && $userDeal['money']<$order['pay_price']){
            if($user['money']>=$order['pay_price']){
                return array('pay_name'=>'储值余额','pay_type'=>10,'pay_price'=>$order['pay_price']);
            }else{
                $this->setError('余额不足，请选择微信支付');
                return false;
            }
        }



    }
    /**
     * 创建新订单
     * @param array $order 订单信息
     * @return bool
     * @throws \Exception
     */
    public function createOrder($order)
    {
        $model = new self;
        $userModel=new User();
        // 创建新的订单
        $status = $model->transaction(function () use ($order) {
            // 创建订单事件
            return $this->add($order);
        });

        // 余额支付标记订单已支付
        if ($status && $order['pay_type'] == PayTypeEnum::BALANCE) {
            if($order['balance_money']!==0){
                $this->error = '余额支付不支持零钱抵扣';
                return false;
            }
            if($order['coupon_id']!=0){
                $this->error = '余额支付不支持优惠券抵扣';
                return false;
            }
            if($order['balance_money']!==0 && $order['coupon_id']!=0){
                $this->error = '优惠券和零钱不能同时抵扣';
                return false;
            }
            //返回余额支付的方式
            $user=$userModel->find($order['user_id']);
            $orders=$model->find($status);

            return  $this->onPaymentByBalances($user,$orders);
        }

        return $status;
    }

    /**
     * 余额支付
     * @param $user
     * @param $order
     * @param $password
     * @param $balanceType
     * @return bool
     * @throws BaseException
     * @throws \think\exception\DbException
     */
    public function onOrderPaymentByBalance($user,$order,$password,$balanceType)
    {
        $result=PaymentService::balance($user,$order,$password,$balanceType);

        if($result==true){
            return $this->onPaymentByBalance($order,$balanceType);
        }else{
            throw new BaseException(['msg' => '支付错误，请稍后重新支付']);
        }
    }
    /**
     * 创建订单事件
     * @param $order
     * @return bool
     * @throws BaseException
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    private function createOrderEvent($order)
    {
        $this->log->info('开始','新建订单事务');
        // 新增订单记录
        $status = $this->add($order);
        $this->log->info(bool2str($status), '订单表新增记录');
        if($order['dis_type']==1){
            // 设置优惠券使用状态
            $ret = UserCouponModel::setIsUse($order['coupon_id']);
            $this->log->info(bool2str($ret), '设置优惠券使用状态');
        }else{
            //设置零钱使用
            $ret = User::setBalance(self::where('order_id',$status)->value('order_no'),$order);
            $this->log->info(bool2str($ret), '设置零钱使用');
        }
        $this->log->info('结束','新建订单事务');
        // 获取订单详情
        return $status;
    }

    /**
     * 新增订单记录
     * @param $order
     * @param string $remark
     * @return false|int
     */
    private function add($order)
    {


        // 订单数据
        $data = [
            'user_id'         => $order['user_id'],
            'order_no'        => $this->orderNo(),
            'total_price'     => $order['order_total_price'],
            'order_price'     => $order['order_price'],
            'coupon_id'       => $order['coupon_id'],
            'coupon_money'    => $order['coupon_money'],
            'balance_money'   => $order['balance_money'],
            'balance_num'     => $order['balance_num'],
            'points_money'    => 0,
            'points_num'      => 0,
            'pay_price'       => $order['order_pay_price'],
            'delivery_type'   => 30,
            'pay_type'        => $order['pay_type'],
            'pay_way'         => 0,
            'buyer_remark'    => $order['remark'],
            'order_source'    => 50,
            'order_source_id' => 0,
            'points_bonus'    => 0,
            'is_fictitious'   => 1,
            'wxapp_id'        =>static::$wxapp_id,
        ];

        // 保存订单记录
         self::isUpdate(false)->save($data);
         return $this->order_id;
    }

}
